package com.dhecp.project.storage.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.core.utils.PageUtils;
import com.dhecp.core.utils.RedisUtil;
import com.dhecp.core.utils.forest.FroestHttPUtils;
import com.dhecp.project.api.util.ApiConfig;
import com.dhecp.project.business.domain.LogisticsMmodeGrads;
import com.dhecp.project.logstics.domain.FbaBox;
import com.dhecp.project.logstics.domain.FbaBoxDetail;
import com.dhecp.project.logstics.mapper.FbaBoxDetailMapper;
import com.dhecp.project.logstics.mapper.FbaBoxMapper;
import com.dhecp.project.logstics.mapper.LogsticsMmodeGradsMapper;
import com.dhecp.project.storage.domain.HwTailprogram;
import com.dhecp.project.storage.domain.HwTailprogramdetail;
import com.dhecp.project.storage.domain.TsChannelcode;
import com.dhecp.project.storage.enums.TailprogramEnum;
import com.dhecp.project.storage.mapper.HwTailprogramMapper;
import com.dhecp.project.storage.mapper.HwTailprogramdetailMapper;
import com.dhecp.project.storage.service.HwTailprogramService;
import com.dhecp.project.storage.service.TsChannelcodeService;
import com.dhecp.project.system.domain.YsDict;
import com.dhecp.project.system.mapper.YsDictMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.dhecp.core.constant.DataFiltering;
import com.dhecp.project.system.service.SysDictionaryForFieldService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.lang.Math.max;

/**
 * 海外仓尾程单(HwTailprogram表)服务实现类
 *
 * @author fxz
 * @since 2023-09-08 10:07:47
 */
@Service("hwTailprogramService")
public class HwTailprogramServiceImpl implements HwTailprogramService {

    private static Logger logger = LoggerFactory.getLogger(HwTailprogramServiceImpl.class);

    @Autowired
    private HwTailprogramMapper hwTailprogramMapper;

    @Autowired
    private HwTailprogramdetailMapper hwTailprogramdetailMapper;
    
    @Autowired
    private SysDictionaryForFieldService dictionaryForFieldService;

    @Autowired
    private YsDictMapper ysDictMapper;

    @Autowired
    private TsChannelcodeService tsChannelcodeService;

    @Autowired
    private LogsticsMmodeGradsMapper logsticsMmodeGradsMapper;

    @Autowired
    private FbaBoxMapper fbaBoxMapper;

    @Autowired
    private FbaBoxDetailMapper fbaBoxDetailMapper;

    /**
     * 通过guid查询单条数据
     *
     * @param params 对象
     * @return 实例对象
     */
    @Override
    public HwTailprogram queryFirstRecord(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        return this.hwTailprogramMapper.selectFirstRecordByNid(params);
    }


    /**
     * 修改尾程方式
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult updateTailProgram(Map<String, Object> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        //查询数字字典表中数据
        YsDict ysDict = ysDictMapper.selectFirstRecordByNid(params);
        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);
            hwTailprogram1.setTailprogram(ysDict.getDictname());
            hwTailprogram1.setTailprogramApi(ysDict.getDictvalue());
            hwTailprogramMapper.update(hwTailprogram1);
        }
        return AjaxResult.success();
    }

    /**
     * 修改渠道代码
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult updateChannel(Map<String, Object> params) throws Exception {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        //查询渠道代码数据
        params1.put("guid",params.get("channelId"));
        TsChannelcode tsChannelcode = tsChannelcodeService.queryFirstRecord(params1);
        if (tsChannelcode == null){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("渠道代码不存在,请核实后在操作!");
        }
        params1.put("logisticsMmodeGuid",tsChannelcode.getGuid());
        params1.put("type","QDDMJZ");
        //查询渠道代码对应的计重单价区间
        List<LogisticsMmodeGrads> logisticsMmodeGradList = logsticsMmodeGradsMapper.findLogisticsMmodeGrads(params1);
        params1.remove("channelId");
        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        Double weightcal = 0.0;
        BigDecimal weightPrice;
        List<LogisticsMmodeGrads> tdjzPrice;
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);
            if (hwTailprogram1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("尾程单不存在,请核实后在操作!");
            }
            //计重
            weightcal = max(hwTailprogram1.getWeightreal(),hwTailprogram1.getWeightvol());
            //梯度计重单价=(实际计重满足区间的值)
            BigDecimal finalWeightcal = BigDecimal.valueOf(weightcal);
            tdjzPrice = logisticsMmodeGradList.stream().filter(logisticsMmodeGrads1 -> finalWeightcal.compareTo(logisticsMmodeGrads1.getStartSection()) >= 0
                    && finalWeightcal.compareTo(logisticsMmodeGrads1.getEndSection()) <= 0).collect(Collectors.toList());
            //梯度计重单价
            weightPrice = tdjzPrice.size()!=0?tdjzPrice.get(0).getKg():BigDecimal.ZERO;
            //尾程费=MAX（抛重，实重）*梯度计重单价+箱子(出库手续费)手续费*箱数+商品手续费*商品数+附加费+透明标手续费*透明标商品数
            //12.19新增 尾程费添加3个费用（拆箱封箱费*箱数 + FBA箱唛（按箱）*箱数 + DPD快递单（按箱）*箱数） 修改一个字段 箱子手续费修改为出库费
            hwTailprogram1.setLastvoyagecharge((weightcal * Double.valueOf(String.valueOf(weightPrice)))
                    + (tsChannelcode.getBoxcommission() * hwTailprogram1.getNumbox())
                    + (tsChannelcode.getGoodscommission() * hwTailprogram1.getNumcommodity())
                    +hwTailprogram1.getAddition()
                    +tsChannelcode.getLucencyCommission() * hwTailprogram1.getLucencyNum()
                     + (tsChannelcode.getCfCommission() * hwTailprogram1.getNumbox())
                     + (tsChannelcode.getFbaCommission() * hwTailprogram1.getNumbox())
                     + (tsChannelcode.getDpdCommission() * hwTailprogram1.getNumbox()));
            hwTailprogram1.setWeightPrice(weightPrice.doubleValue());
            hwTailprogram1.setBoxCommission(tsChannelcode.getBoxcommission());
            hwTailprogram1.setGoodsCommission(tsChannelcode.getGoodscommission());
            hwTailprogram1.setCfCommission(tsChannelcode.getCfCommission());
            hwTailprogram1.setFbaCommission(tsChannelcode.getFbaCommission());
            hwTailprogram1.setDpdCommission(tsChannelcode.getDpdCommission());
            hwTailprogram1.setWeightcal(weightcal);
            hwTailprogram1.setChannelcode(tsChannelcode.getCode());
            hwTailprogram1.setCurrency(tsChannelcode.getCurrency());
            hwTailprogram1.setCodeqdcompany(tsChannelcode.getCodecompany());
            hwTailprogram1.setNamecompany(tsChannelcode.getNamecompany());
            hwTailprogram1.setLucencyCommission(String.valueOf(tsChannelcode.getLucencyCommission()));
            hwTailprogramMapper.update(hwTailprogram1);
        }
        return AjaxResult.success();
    }


    /**
     * 修改状态
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult updateStateName(Map<String, Object> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);
            if (hwTailprogram1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("尾程单不存在,请核实后在操作!");
            }
            //0.审核 |1回退
            if (params.get("num").equals("0")){
                if (hwTailprogram1.getTailprogram() == null){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("选择单据中未选择尾程方式,请核实后在操作!");
                }
                if (hwTailprogram1.getChannelcode() == null){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("选择单据中未选择渠道代码,请核实后在操作!");
                }
                hwTailprogram1.setStateName(TailprogramEnum.StateName.SUCCESS.value);
                hwTailprogram1.setUpdatetime(new Date());
            }else {
                if (!hwTailprogram1.getStateName().equals(TailprogramEnum.StateName.SUCCESS.value)){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("选择单据中状态只允许是已审核,请核实后在操作!");
                }
                hwTailprogram1.setStateName(TailprogramEnum.StateName.INIT.value);
                hwTailprogram1.setUpdatetime(null);
            }
            hwTailprogramMapper.updateStateName(hwTailprogram1);
        }
        return AjaxResult.success();
    }

    /**
     * 修改附加费
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult updateAddition(Map<String, Object> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        Double drAddition = Double.valueOf(String.valueOf(params.get("drAddition")));
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);
            if (hwTailprogram1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("尾程单不存在,请核实后在操作!");
            }
            //删除之前的附加费 在加上现在的附加费
            hwTailprogram1.setLastvoyagecharge(hwTailprogram1.getLastvoyagecharge() - hwTailprogram1.getAddition() + drAddition);
            hwTailprogram1.setAddition(drAddition);
            hwTailprogramMapper.update(hwTailprogram1);
        }
        return AjaxResult.success();
    }

    /**
     * 修改出库单
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult updateStockOutCode(Map<String, Object> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        String stockOutCode = String.valueOf(params.get("stockOutCode"));
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);
            if (hwTailprogram1 == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("尾程单不存在,请核实后在操作!");
            }
            if (!hwTailprogram1.getStateName().equals(TailprogramEnum.StateName.SUCCESS.value)){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("选择单据中状态只允许是已审核,请核实后在操作!");
            }
            hwTailprogram1.setStockOutCode(stockOutCode);
            hwTailprogramMapper.update(hwTailprogram1);
        }
        return AjaxResult.success();
    }

    /**
     * 删除
     * @param params
     * @return
     */
    @Override
    @Transactional(timeout = 300, propagation = Propagation.REQUIRES_NEW)
    public AjaxResult delete(Map<String, Object> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();
        HwTailprogram hwTailprogram1;

        List<HwTailprogram> hwTailprogramList = JSON.parseArray(params.get("infoItems").toString(), HwTailprogram.class);
        for (HwTailprogram hwTailprogram : hwTailprogramList){
            params1.put("guid",hwTailprogram.getGuid());
            hwTailprogram1 = hwTailprogramMapper.selectFirstRecordByNid(params1);

            hwTailprogramMapper.delete(hwTailprogram1.getGuid());
            hwTailprogramdetailMapper.deleteTpCode(hwTailprogram1.getBid());
        }

        return AjaxResult.success();
    }

    /**
    * 查询列表数据
    */
    @Override
    public List<HwTailprogram> queryList(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));	//常规查询条件SQL语句

        if (params.get("field") == null || params.get("field") == ""){
            String orderBy = "t1.createTime DESC";
            PageUtils.startPageOrder(orderBy);
        }else{
            PageUtils.startPage();
        }
        return this.hwTailprogramMapper.select(params);
    }

    /**
     * 导入并直接回填追踪编号单据
     * @return
     * @author fxz
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public AjaxResult importData(Map<String, Object> params) {
        JSONArray jsonArray = JSON.parseArray(params.get("infoItems").toString());
        Map<String, List<String>> params1 = new HashMap<String, List<String>>();
        List<String> stateTrackCodeList = null;
        String shipmentId = "";
        String stateTrackCode = "";
        List<HwTailprogram> hwTailprogramList = new ArrayList<>();
        HwTailprogram hwTailprogram;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = (JSONObject) jsonArray.get(i);
            if (jsonObject.get("shipmentid") != null){
                shipmentId = jsonObject.get("shipmentid").toString();
                stateTrackCode = jsonObject.get("trackingcode").toString();
                if (shipmentId.indexOf("FBA") == -1){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("导入数据出错!");
                } else {
                    if (params1.get(shipmentId) == null){
                        stateTrackCodeList = new ArrayList<>();
                        stateTrackCodeList.add(stateTrackCode);
                        params1.put(shipmentId,stateTrackCodeList);
                        hwTailprogram = new HwTailprogram();
                        hwTailprogram.setShipmentid(shipmentId);
                        hwTailprogramList.add(hwTailprogram);
                    } else {
                        stateTrackCodeList = params1.get(shipmentId);
                        stateTrackCodeList.add(stateTrackCode);
                        params1.put(shipmentId,stateTrackCodeList);
                    }

                }
            }
        }

        //批量查询尾程信息
        List<HwTailprogram> hwTailprogramBatch = hwTailprogramMapper.findHwTailprogramBatch(hwTailprogramList);
        //批量查询尾程详情信息
        List<HwTailprogramdetail> hwTailprogramDetailBatch = hwTailprogramdetailMapper.findHwTailprogramdetailBatch(hwTailprogramBatch);
        //批量查询装箱单数据
        List<FbaBox> findFbaBoxBatchList = fbaBoxMapper.findFbaBoxHwBatch(hwTailprogramBatch);
        //头程完成单箱子数据
        List<FbaBoxDetail> findFbaBoxDetailBatchList = fbaBoxDetailMapper.fbaBoxDetailBatchList(findFbaBoxBatchList);


        List<HwTailprogramdetail> hwTailprogramdetailList = null;
        List<FbaBox> findFbaBoxNewList;
        List<FbaBoxDetail> findFbaBoxDetailNewList;
        List<HwTailprogram> hwTailprogramListNew;
        for (Map.Entry<String,List<String>> entry: params1.entrySet()) {
            hwTailprogramListNew = hwTailprogramBatch.stream().filter(hwTailprogram1 -> hwTailprogram1.getShipmentid().equals(entry.getKey()
            )).collect(Collectors.toList());
            if (hwTailprogramListNew.size() == 0){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("FBA编号:"+entry.getKey()+"数据不存在,请核实后再操作!");
            }
            if (hwTailprogramListNew.get(0).getNumbox() != entry.getValue().size()){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return AjaxResult.error("FBA编号:"+entry.getKey()+"数据箱数与上传数据追踪编号数据不匹配,请核实后再操作!");
            }

            //设置尾程详情的追踪编码
            HwTailprogram hwTailprogram1 = hwTailprogramListNew.get(0);
            hwTailprogramdetailList = hwTailprogramDetailBatch.stream().filter(hwTailprogramdetail -> hwTailprogramdetail.getTpcode().equals(hwTailprogram1.getBid()
            )).collect(Collectors.toList());
            for (int i = 0; i < hwTailprogramdetailList.size(); i++) {
                if (entry.getValue().get(i).equals("") || entry.getValue().get(i) == null){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("FBA编号:"+hwTailprogram1.getShipmentid()+"追踪编号为空,请核实后再操作!");
                }

                hwTailprogramdetailList.get(i).setTrackingcode(entry.getValue().get(i));
            }

            //修改头程完成单信息
            findFbaBoxNewList = findFbaBoxBatchList.stream().filter(fbaBox -> fbaBox.getCode().equals(hwTailprogram1.getCodebox()))
                    .collect(Collectors.toList());
            findFbaBoxNewList.get(0).setTrackingTime(new Date());
            findFbaBoxNewList.get(0).setStateTrack("4");
            findFbaBoxNewList.get(0).setStateTrackName("追踪编号已导入");

            //修改头程箱子数据
            findFbaBoxDetailNewList = findFbaBoxDetailBatchList.stream().filter(fbaBoxDetail -> fbaBoxDetail.getCodeBox().equals(hwTailprogram1.getCodebox()
            )).collect(Collectors.toList());
            for (int i = 0; i < findFbaBoxDetailNewList.size(); i++) {
                if (entry.getValue().get(i).equals("") || entry.getValue().get(i) == null){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return AjaxResult.error("FBA编号:"+hwTailprogram1.getShipmentid()+"追踪编号为空,请核实后再操作!");
                }

                findFbaBoxDetailNewList.get(i).setTrackingCode(entry.getValue().get(i));
            }
            //设置追踪编号
            hwTailprogram1.setTrackingcode(String.join(",",entry.getValue()));
        }

        if (hwTailprogramBatch.size() != 0){
            int updateLength = hwTailprogramBatch.size();
            int i = 0;
            while (updateLength > 90) {
                hwTailprogramMapper.batchUpdateNew(hwTailprogramBatch.subList(i, i + 90));
                i = i + 90;
                updateLength = updateLength - 90;
            }
            if (updateLength > 0) {
                hwTailprogramMapper.batchUpdateNew(hwTailprogramBatch.subList(i, i + updateLength));
            }
        }

        //修改尾程详情的追踪编号
        if (hwTailprogramDetailBatch.size() != 0){
            int updateLength = hwTailprogramDetailBatch.size();
            int i = 0;
            while (updateLength > 90) {
                hwTailprogramdetailMapper.batchUpdate(hwTailprogramDetailBatch.subList(i, i + 90));
                i = i + 90;
                updateLength = updateLength - 90;
            }
            if (updateLength > 0) {
                hwTailprogramdetailMapper.batchUpdate(hwTailprogramDetailBatch.subList(i, i + updateLength));
            }
        }

        //修改装箱详情的追踪编号
        if (findFbaBoxBatchList.size() != 0){
            int updateLength = findFbaBoxBatchList.size();
            int i = 0;
            while (updateLength > 90) {
                fbaBoxMapper.updateBatchCode(findFbaBoxBatchList.subList(i, i + 90));
                i = i + 90;
                updateLength = updateLength - 90;
            }
            if (updateLength > 0) {
                fbaBoxMapper.updateBatchCode(findFbaBoxBatchList.subList(i, i + updateLength));
            }
        }

        //修改头程箱子数据
        if (findFbaBoxDetailBatchList.size() != 0){
            int updateLength = findFbaBoxDetailBatchList.size();
            int i = 0;
            while (updateLength > 50) {
                fbaBoxDetailMapper.batchUpdate(findFbaBoxDetailBatchList.subList(i, i + 50));
                i = i + 50;
                updateLength = updateLength - 50;
            }
            if (updateLength > 0) {
                fbaBoxDetailMapper.batchUpdate(findFbaBoxDetailBatchList.subList(i, i + updateLength));
            }
        }

        return AjaxResult.success("导入成功");
    }

    /**
     * 物流对账调用数据
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    public List<HwTailprogram> queryListSelect(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");	//查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));	//常规查询条件SQL语句
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));	//数据权限查询条件SQL语句

        PageUtils.startPage();

        return hwTailprogramMapper.queryListSelect(params);
    }
}

